﻿using System;
using System.Collections.Generic;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Testing;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

namespace ZQNB.Common.NHExtensions
{
    public static class NbSessionFactoryForApp
    {
        /// <summary>
        /// 全局统一SF初始化，一般在Application_Start方法中调用。
        /// 一次调用初始化一个SessionFactory
        /// </summary>
        /// <param name="dbCfg">NH数据库配置</param>
        /// <param name="mappings">NH映射配置</param>
        /// <param name="buildSchema">是否自动创建或重新创建数据库表，默认不创建</param>
        /// <param name="sfName">SF名，标识不同的SF, 默认为空串</param>
        /// <param name="script"></param>
        /// <param name="export"></param>
        /// <param name="justDrop"></param>
        public static void InitSessionFactory(IPersistenceConfigurer dbCfg,
                                            Action<MappingConfiguration> mappings,
                                            bool buildSchema = false,
                                            string sfName = "", bool script = true, bool export = true, bool justDrop = false)
        {
            try
            {
                if (_sessionFactories.ContainsKey(sfName))
                    throw new ArgumentException("Duplicate Session Factory name");

                var cfg = Fluently.Configure()
                            .Database(dbCfg)
                            .Mappings(mappings)
                            .BuildConfiguration();

                if (buildSchema)
                    BuildSchema(cfg, script, export, justDrop);

                _sessionFactories[sfName] = cfg.BuildSessionFactory();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 通过初始化时使用的SF名，用相应的SF来创建NH的ISession，使用者负责ISession的释放
        /// </summary>
        /// <param name="sfName">初始化SF时用的SF名, 默认为空串</param>
        /// <returns>NH的ISession</returns>
        public static ISession OpenSession(string sfName = "")
        {
            return _sessionFactories[sfName].OpenSession();
        }

        public static ISessionFactory SessionFactory(string sfName = "")
        {
            if (_sessionFactories.ContainsKey(sfName))
            {
                return _sessionFactories[sfName];
            }
            return null;
        }

        private static void BuildSchema(Configuration configuration, bool script = true, bool export = true, bool justDrop = false)
        {
            new SchemaExport(configuration).Execute(script, export, justDrop);
        }

        private static void CreateSchema(Configuration cfg)
        {
            var schemaExport = new SchemaExport(cfg);
            schemaExport.Drop(false, true);
            schemaExport.Create(false, true);
        }

        private static readonly Dictionary<string, ISessionFactory> _sessionFactories = new Dictionary<string, ISessionFactory>();
    }
}